
#include <assert.h>

#include "OperatorNode.hpp"
#include "Symbols.hpp"

OperatorNode::OperatorNode() :
        ExpressionNode(),
        _operator(-1),
        _left(0),
        _right(0)
{

}


OperatorNode::OperatorNode(int p_operator) :
        ExpressionNode(),
        _operator(p_operator),
        _left(0),
        _right(0)
{

}

OperatorNode::~OperatorNode()
{
    if (this->_left != 0)
        delete this->_left;
    if (this->_right != 0)
        delete this->_right;
}

Tribool OperatorNode::solve(Universe& universe)
{
    if (this->_solved)
        return this->_value;
    Tribool left(TriboolVal::Undefined);
    if (this->_operator != NOT)
    {
        assert(this->_left != 0);
        left = this->_left->solve(universe);
    }
    assert(this->_right != 0);
    Tribool right = this->_right->solve(universe);
    Tribool result(TriboolVal::Undefined);
    switch (this->_operator)
    {
    case AND :
        result = left && right;
        break;
    case OR :
        result = left || right;
        break;
    case XOR :
        result = left ^ right;
        break;
    case NOT :
        result = !right;
        break;
    }
    this->_solved = true;
    this->_value = result;
    return this->_value;
}

ExpressionNode* OperatorNode::clone(std::map<int, ExpressionNode*>& existingNodes)
{
    if (existingNodes.find(this->_id) != existingNodes.end())
        return existingNodes[this->_id];
    OperatorNode* clone = new OperatorNode(this->_operator);
    clone->_id = this->_id;
    clone->_solved = this->_solved;
    clone->_value = this->_value;
    existingNodes[this->_id] = clone;
    clone->_left = (this->_left != 0) ? this->_left->clone(existingNodes) : 0;
    clone->_right = (this->_right != 0) ? this->_right->clone(existingNodes) : 0;
    return clone;
}

void OperatorNode::setLeft(ExpressionNode* left)
{
    this->_left = left;
}

void OperatorNode::setRight(ExpressionNode* right)
{
    this->_right = right;
}

void OperatorNode::addChild(ExpressionNode* child)
{
    if (this->_operator == NOT)
        this->_right = child;
}

NodeType::Type OperatorNode::getType() const
{
    return NodeType::Operator;
}
